/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package VocSymbTest2;


import java.util.ArrayList;
import java.util.Iterator;

/**
 *
 * @author StiggieBig
 */

public class GrammarString implements Comparable<GrammarString>, Iterable<VocabularySymbol>{
    /**
	 * 
	 */

	public ArrayList<VocabularySymbol> grammarString;
    
    public VocabularySymbolSet<Terminal> first;
    
    public GrammarString(){
        grammarString = new ArrayList<VocabularySymbol>();
        grammarString.clear();
        first = new VocabularySymbolSet<Terminal>();
    }

    public GrammarString(VocabularySymbol symb){
        grammarString = new ArrayList<VocabularySymbol>();
        grammarString.add(symb);
        first = new VocabularySymbolSet<Terminal>();
    }
    
    // copy constructor
    public GrammarString(GrammarString copyFrom) {
        grammarString = new ArrayList<VocabularySymbol>();
        first = new VocabularySymbolSet<Terminal>();
        
        grammarString.clear();
        for (VocabularySymbol tempVocabularySymbol : copyFrom.grammarString) {
        	grammarString.add(tempVocabularySymbol);
        }
        first = copyFrom.first;
    }
    
    
    public boolean isEmpty(){
    	return grammarString.isEmpty();
    }
    public boolean add(VocabularySymbol newVocSymb){
    	return grammarString.add(newVocSymb);
    }
    
    public VocabularySymbol remove(int index){
    	return grammarString.remove(index);
    }
    
    public void SetFirst(Grammar grammar) {
	    boolean hasEmpty = true;
	    Terminal empty = (Terminal)(grammar.allTerminals.GetVocSymbFromChar('e'));
	    
	    for(Iterator<VocabularySymbol> it =  this.iterator(); hasEmpty && it.hasNext();){
	    	VocabularySymbol tempVocSymb = it.next();
	    	for(Terminal aFirstTerm : tempVocSymb.GetFirst()){
	    		if(aFirstTerm != empty){
	    			this.AddToFirst(aFirstTerm);
	    		}
	    		hasEmpty = tempVocSymb.isInFirst(empty);
	    	}
	    }
	    if(hasEmpty){
	    	this.AddToFirst(empty);
	    }
	}
    
    /*public <T extends VocabularySymbol> void SetFirst(VocabularySymbolSet<T> checked, Grammar grammar) {
        boolean hasEmpty = true;
        Terminal empty = (Terminal)(grammar.allTerminals.GetVocSymbFromChar('e'));
        Terminal testTermObj = new Terminal();
        Terminal tempTerminal = new Terminal();
        NonTerminal testNonTermObj = new NonTerminal();
        if(this.getClass() == testTermObj.getClass()){
            tempTerminal = new Terminal((Terminal)this);
            this.first.vocabularySymbolSet.add(tempTerminal);
        }
        else if(this.getClass() == testNonTermObj.getClass()){
            for(GrammarRule nextGramRule : allGrammarRules.grammarRuleSet){
                if(this.GetSymbolChar() == nextGramRule.GetSource().GetSymbolChar()){
                    for (Iterator<VocabularySymbol> it = nextGramRule.GetTarget().grammarString.iterator(); hasEmpty && it.hasNext();) {
                        VocabularySymbol nextVocSymbInNextGramRule = it.next();
                        if(!checked.vocabularySymbolSet.contains(nextVocSymbInNextGramRule)){
                            checked.vocabularySymbolSet.add(nextVocSymbInNextGramRule);
                            nextVocSymbInNextGramRule.SetFirst(checked, allGrammarRules);
                            for(VocabularySymbol nexttermInNextVocSymbInNextGramRule : nextVocSymbInNextGramRule.first.vocabularySymbolSet){
                                if(!this.GetFirst().vocabularySymbolSet.contains(nexttermInNextVocSymbInNextGramRule)){
                                    this.first.vocabularySymbolSet.add(nexttermInNextVocSymbInNextGramRule);
                                }
                            }
                        }
                        hasEmpty = nextVocSymbInNextGramRule.first.vocabularySymbolSet.contains(empty);
                    }
                    if(hasEmpty){
                        this.first.vocabularySymbolSet.add(empty);
                    }
                    hasEmpty = true;
                }
            }
        }
    }*/

    public VocabularySymbol GetInitialSymb(){
    	return (VocabularySymbol)grammarString.get(0);
    }
    
    void Print(){
        for (VocabularySymbol tempVocabularySymbol : grammarString) {
            tempVocabularySymbol.Print();
        }
    }
    
    void PrintDebug(){
    	for (VocabularySymbol tempVocabularySymbol : grammarString) {
            System.out.print("the vocabulary symbol: ");
            tempVocabularySymbol.Print();
            System.out.println(" is of type: " + tempVocabularySymbol.getClass());
        }
    }
    
    public void AddToFirst(Terminal terminal){
    	first.add(terminal);
    }
    
    public VocabularySymbolSet<Terminal> GetFirst() {
        return first;
    }
    
    public int size(){
    	return grammarString.size();
    }

    @Override
    public int compareTo(GrammarString s) {
    	int compVal = 0;
        Iterator<VocabularySymbol> it1 = this.iterator();
        Iterator<VocabularySymbol> it2 = s.iterator();
        
        if(this.size() < s.size()){
        	compVal = -1;
        }else if(this.size() > s.size()){	
        	compVal = 1;
        }else if(this.size() != 0){
        	while(compVal == 0 && it1.hasNext() && it2.hasNext()){
	        	VocabularySymbol tempVocabSymbol1 = (VocabularySymbol) it1.next();
	        	VocabularySymbol tempVocabSymbol2 = (VocabularySymbol) it2.next();
	            compVal = tempVocabSymbol1.compareTo(tempVocabSymbol2);
        	}
        }
        return compVal;
    }

	@Override
	public Iterator<VocabularySymbol> iterator() {
		// TODO Auto-generated method stub
		return grammarString.iterator();
	}
}
